package swing.project.standard;

import static java.lang.System.out;

import java.awt.Color;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import java.util.ResourceBundle;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.filechooser.FileNameExtensionFilter;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import work.utils.StandardUtils;

import com.h819.core.commons.Configurations;
import com.h819.core.file.MyFileUtils;
import com.h819.core.file.excel.poi.POIUtils;
import com.h819.core.utils.MyDateUtils;
import com.h819.core.utils.MyMessageException;
import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;

/**
 * @Title: SwingWorkerExampleJPanel.java
 * @Description: TODO(结合 JProgressMonitor，演示 SwingWorker 的用法。具体例子参见 PDF 项目)
 * @author H819
 * @date 2011-2-24
 * @version V1.0
 */
public class JPanelSwingWorkerCheckTilu extends JPanel implements
		PropertyChangeListener {

	// 都列为全局变量，便于在下面的方法中都能调用。
	private JLabel announceLable;
	private JLabel messageLabel;
	private JProgressBar progressBar;
	// ProgressMonitor 不好操控，不用这个组件
	// private ProgressMonitor progressMonitor;
	private JButton buttonStart;
	private JButton buttonCancel;

	private final JFileChooser fileChooser = new JFileChooser();

	private static final ResourceBundle BUNDLE = ResourceBundle
			.getBundle("swing.project.standard.messages"); //$NON-NLS-1$
	// 加载配置文件
	PropertiesConfiguration conf = Configurations.getInstance(new File(BUNDLE
			.getString("app.config.filepath")));

	// 提示信息
	private String message = "";

	// 题录总数
	private int allnum = 0;
	// 验证正确的总数
	private int rightallnum = 0;

	// 错误题录信息的行数，跳过表头，从第3行开始
	private int wrongallno = 3;

	private Task task;

	// 传入的文件
	private File excelFile;
	// 从平台中查出来的类别代码

	private static Logger log = Logger
			.getLogger(JPanelSwingWorkerCheckTilu.class);
	private JLabel lblNewLabel;

	/**
	 * Create the panel.
	 */
	public JPanelSwingWorkerCheckTilu() {
		setLayout(new FormLayout(new ColumnSpec[] {
				FormFactory.RELATED_GAP_COLSPEC, ColumnSpec.decode("81px"),
				FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
				ColumnSpec.decode("233px"), }, new RowSpec[] {
				RowSpec.decode("36px"), RowSpec.decode("15px"),
				FormFactory.NARROW_LINE_GAP_ROWSPEC, RowSpec.decode("19px"),
				RowSpec.decode("33px"), RowSpec.decode("75px"),
				RowSpec.decode("33px"), RowSpec.decode("23px"), }));

		lblNewLabel = new JLabel(BUNDLE.getString("CheckTilu.titel.text")); //$NON-NLS-1$ //$NON-NLS-2$
		add(lblNewLabel, "2, 1");

		messageLabel = new JLabel(
				BUNDLE.getString("CheckTilu.messageLabel.text")); //$NON-NLS-1$ //$NON-NLS-2$
		add(messageLabel, "2, 2, 3, 1, left, top");

		buttonStart = new JButton(
				BUNDLE.getString("CheckTilu.button.chosefile.text")); //$NON-NLS-1$ //$NON-NLS-2$

		// 设置配置文件中指定的目录
		fileChooser.setCurrentDirectory(new File(conf
				.getString("config.excel.tilucheck.root")));

		fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("*.xls",
				"xls"));

		buttonStart.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {

				// 获得传入的文件
				int returnValue = fileChooser.showOpenDialog(null);
				if (returnValue == JFileChooser.APPROVE_OPTION) {

					excelFile = fileChooser.getSelectedFile();
					log.info(excelFile.getPath());

					String extention = FilenameUtils.getExtension(
							excelFile.getAbsolutePath()).toLowerCase();

					if (!extention.equals("xls") && !extention.equals("xlsx")) {

						// 此处弹出对话框
						JOptionPane.showMessageDialog(
								JPanelSwingWorkerCheckTilu.this,
								"请选择  excel 文件");
						task.cancel(true);
						return;
					}

				} else {
					task.cancel(true);
					log.info("task cancel.");
					return;
				}

				progressBar.setValue(0);

				// start
				task = new Task();
				// 为 task 添加监听器，该监听器实现方法是下文的 propertyChange 方法。
				task.addPropertyChangeListener(JPanelSwingWorkerCheckTilu.this);
				buttonStart.setEnabled(false);

				task.execute();

				log.info("start");

			}
		});

		progressBar = new JProgressBar(0, 100);
		progressBar.setStringPainted(true);
		progressBar.setBackground(Color.orange);
		progressBar.setForeground(Color.red);
		add(progressBar, "2, 4, 3, 1, left, top");

		announceLable = new JLabel(BUNDLE.getString("CheckTilu.maininfo.text")); //$NON-NLS-1$ //$NON-NLS-2$
		add(announceLable, "2, 6, 3, 1, left, top");

		add(buttonStart, "2, 8, left, top");

		buttonCancel = new JButton(BUNDLE.getString("CheckTilu.button.cancel")); //$NON-NLS-1$ //$NON-NLS-2$
		buttonCancel.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {

				// cancel
				task.cancel(true);

			}
		});

		add(buttonCancel, "4, 8, left, top");

	}

	/**
	 * 执行任务的内部类，想要执行的操作，在这里执行。
	 * 
	 * 在这个类中，仅需要处理的任务一、二即可，其他的代码不要改动.
	 * 
	 * @ClassName: Task
	 * @Description: TODO(执行任务的内部类，想要执行的操作，在这里执行。)
	 * @author h819
	 * @date 2010-10-6 下午10:31:31
	 * @version V1.0
	 */

	class Task extends SwingWorker<Void, Void> {

		/**
		 * 
		 * 因为 done 中用到了这些变量，故设置为类变量
		 */

		// 准备生成 excel 结果文件，如果文件被占用，则进行提示。
		FileOutputStream outRightSteam = null;
		FileOutputStream outWrongSteam = null;

		Workbook wbright = null;
		Workbook wbwrong = null;

		// 待验证的 excel 文件所在目录
		String workFolderPath = "";

		// === 准备文件名
		// 通过验证的excel文件名称，只有一个
		String right_standard_filepath = "";

		// 没有通过验证的excel文件名称，每次都新生成一个，用时间作为文件名
		String wrong_standard_filepath = "";

		// 未通过验证原因记录文件名称，每次覆盖，记录最后一次的结果
		String wrong_standard_Info_filepath = "";

		// 源文件，已经校验完成的文件，仅改名
		String excelFile_rename = "";

		// 存放完全正确的题录，可以从原 excel 文件拷贝到最终的结果中。
		// ArrayList<String> rightList = new ArrayList<String>();

		// 存放错误提示信息
		ArrayList<String> wrongList = new ArrayList<String>();

		@Override
		// 执行任务的方法 ，当 progress =100 时，该方法自动停止执行
		public Void doInBackground() {
			Random random = new Random();

			/**
			 * progress 是 SwingWorker 默认的约束属性，下文的
			 * propertyChange(PropertyChangeEvent evt)也是 SwingWorker
			 * 中的默认方法，该方法跟踪 progress 变化。
			 * 
			 * progress 变量是一个从0到100的整型值。
			 * 
			 * progress 的变化通过 setProgress(0)体现。
			 * 
			 * 创建一个临时变量，模拟 SwingWorker 默认的约束属性 progress，为 int 类型
			 * 
			 * 使其变化范围为 [0,100]，每次增长步长为 1 即在 100 次的变化范围内，完成任务
			 * 
			 * 所以，主要是寻找 progress 的增长时机
			 */
			int progress = 0;
			setProgress(0);

			// log.info("progressMonitorMaxProgress :"+ProgressMonitorPanel.this.progressMonitorMaxProgress);
			// Thread.sleep(500);
			Set<String> lines = POIUtils.readExcel(excelFile);

			/**
			 * 需要处理的任务一：开始
			 * 
			 * 根据具体情况求得任务总数
			 * */
			int count = lines.size();
			allnum = count;
			/**
			 * 需要处理的任务一：完成
			 * */

			/**
			 * 需要处理的任务二：开始
			 * */
			// 其他必要的前期准备工作，不要放在 while 循环中处理的，在此处实现。

			// 判断是否是按照模板导入的
			String lineString0 = (String) CollectionUtils.get(lines, 0);
			String lineString1 = (String) CollectionUtils.get(lines, 1);
			String importTempelettagcn = POIUtils.getColumValue(lineString0, 0);
			String importTempelettagen = POIUtils.getColumValue(lineString1, 0);
			if (importTempelettagcn == null || importTempelettagen == null
					|| !importTempelettagcn.equals("标准号")
					|| !importTempelettagen.equals("STANDARD_CODE")) {
				// 此处弹出对话框
				JOptionPane.showMessageDialog(JPanelSwingWorkerCheckTilu.this,
						"请使用批量导入模板验证数据");
				return null;
			}// 判断完毕

			// for (String s : lines)
			// out.println("line : " + s);

			// 待验证的 excel 文件所在目录
			workFolderPath = FilenameUtils.getFullPath(excelFile.getPath());

			// === 准备文件名
			// 通过验证的excel文件名称，只有一个
			right_standard_filepath = workFolderPath + "right_standard"
					+ MyDateUtils.getToday(MyDateUtils.getToday("_yyyy-MM-dd"))
					+ ".xls";

			// 没有通过验证的excel文件名称，每次都新生成一个，用时间作为文件名
			wrong_standard_filepath = workFolderPath
					+ "wrong_standard"
					+ MyDateUtils.getToday(MyDateUtils
							.getToday("_yyyy-MM-dd_HH_mm_ss")) + ".xls";

			// 未通过验证原因记录文件名称，每次覆盖，记录最后一次的结果
			wrong_standard_Info_filepath = workFolderPath + "wrong_standard"
					+ MyDateUtils.getToday(MyDateUtils.getToday("_yyyy-MM-dd"))
					+ ".txt";

			// 源文件，已经校验完成的文件，仅改名
			excelFile_rename = workFolderPath
					+ FilenameUtils.getBaseName(excelFile.getPath())
					+ "_已经验证完成" + "."
					+ FilenameUtils.getExtension(excelFile.getPath());

			log.info("workFolderPath :" + workFolderPath);
			log.info("right_standard_filepath :" + right_standard_filepath);
			log.info("wrong_standard_filepath :" + wrong_standard_filepath);
			log.info("wrong_standard_Info_filepath :"
					+ wrong_standard_Info_filepath);
			log.info("excelFile_rename :" + excelFile_rename);

			// 删除由于程序非正常终止而生成的0字节的文件
			File fileRight = new File(right_standard_filepath);
			if (fileRight.exists() && FileUtils.sizeOf(fileRight) == 0)
				fileRight.delete();

			// 按照当前时间命名的错误文件，可能有多个，所以逐一判断删除
			File[] fw = new File(workFolderPath).listFiles();

			for (File f : fw) {
				String fname = FilenameUtils.getBaseName(f.getName());

				if (f.isDirectory())
					continue;

				if (FilenameUtils.getExtension(f.getAbsolutePath()).equals(
						"xls")
						&& StringUtils.contains(fname, "wrong_standard")
						&& FileUtils.sizeOf(f) == 0) {
					f.deleteOnExit();
				}

			}
			// 删除 0 字节文件完成

			// 获取模板文件
			MyFileUtils mf = new MyFileUtils();

			String template_filepath = null;
			try {
				template_filepath = mf.getResourceFilePath("/template.xls");

			} catch (MyMessageException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
				return null;
			}

			// 正确的结果，模板文件
			String templatefilepathright = "";
			// 如果文件已经存在，说明已经进行过验证了，直接在验证成功的文件后面追究成功信息。
			if (fileRight.exists() && FileUtils.sizeOf(fileRight) != 0) {
				templatefilepathright = fileRight.getPath();

			} else {// 否则，从资源文件中读取模板，在模板文件上添加数据。

				templatefilepathright = template_filepath;
			}

			try {

				// 载入 excel，准备写入
				wbright = new HSSFWorkbook(new FileInputStream(
						templatefilepathright));

				wbwrong = new HSSFWorkbook(new FileInputStream(
						template_filepath));

				outRightSteam = new FileOutputStream(right_standard_filepath);

				outWrongSteam = new FileOutputStream(wrong_standard_filepath);

				log.info("creat stream");

			} catch (IOException e) {
				// 此处弹出对话框
				JOptionPane.showMessageDialog(JPanelSwingWorkerCheckTilu.this,
						"请关闭打开的 excel 文件");
				e.printStackTrace();
				return null;
			}

			Sheet sheetright = wbright.getSheetAt(0);
			Sheet sheetwrong = wbwrong.getSheetAt(0);
			Row row = null;

			// 正确的结果，从空白行开始追加
			int rownumright = sheetright.getLastRowNum() + 1;
			// 错误文件是新建立的，也从空白行开始追加
			int rownumwrong = sheetwrong.getLastRowNum() + 1;

			// === 创建模拟任务完成。

			int increaseCount = 0;
			int lineSize = lines.size();
			// int progressIncreaseStep = lineSize / 100 + 1;

			log.info("i :" + increaseCount);
			log.info("lines size :" + lineSize);
			log.info("begin row number :" + rownumright);

			/**
			 * 需要处理的任务二：完成
			 * */

			// progressBar 增长步长.
			// 因为总量为 100%,增长 100 次，达到总数。
			float countTofloat = count * 1.0f;
			int step = Math.round(countTofloat / 100f);
			// 开始时机
			int i = 0;

			// 怎么设计一个过程，是 progress 在 100 次的增长过程中，完成
			// 所有的任务。

			// 只有 i < count 条件和任务相关。不同的任务，设置不同的停止条件即可
			while (progress < 100 && !isCancelled() && i <= count) {

				// 如果处理的任务耗时很短，就加上一段延迟的代码，便于看清楚执行过程。
				try {
					Thread.sleep(random.nextInt(50));

				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				// 已经到达任务总数，而 progress 还没到 100，直接赋值 progress 为 100，程序结束运行
				// 保证当处理程序中有一些 contine 语句直接回到 while 判断时，progress 能被赋值
				if (i == count) {
					progress = 100;
					out.println(" **************** update progress = "
							+ progress);

					// 更新参数
					setProgress(progress);
				}

				/**
				 * 
				 * 仅在下面处理任务即可
				 * 
				 * 需要处理的任务二：
				 * 
				 * 循环 i，直至 i=count，任务才算完成
				 * 
				 * 有异常情况判断时，不要用 coninue
				 * 
				 * coninue 会跳过下面的 progress 增长语句. 用 if else 来实现异常情况的判断。
				 **/

				// === 此处处理任务开始
				if (i == 0 || i == 1) {// 跳过前两行
					i++;
					continue;
				}

				StringBuilder wrongInfo = new StringBuilder();

				// 以下逐行处理
				String lineString = (String) CollectionUtils.get(lines, i);

				// 替换字符串中的特殊字符
				lineString = StandardUtils.getFormatString(lineString);

				log.info("开始处理第 " + i + " 行： " + lineString);
				out.println("开始处理第 " + i + " 行： " + lineString);

				log.info("doSomething(): i = " + i);
				out.println("doSomething(): i = " + i);

				// 标准号
				String STANDARD_CODE = POIUtils.getColumValue(lineString, 0);
				// 修正后的标准号
				STANDARD_CODE = StandardUtils.getStandardCode(STANDARD_CODE);
				log.info("STANDARD_CODE :" + STANDARD_CODE);
				if (STANDARD_CODE == null
						|| !StandardUtils.isGNStandardCode(STANDARD_CODE))
					wrongInfo.append(";标准号不合法");

				// 中文名称
				String NAMECN = POIUtils.getColumValue(lineString, 1);
				log.info("NAMECN :" + NAMECN);
				if (NAMECN != null && !StandardUtils.isNameCN(NAMECN))
					wrongInfo.append(";中文名称不能为空");

				// 英文名称
				String NAMEEN = POIUtils.getColumValue(lineString, 2);
				log.info("NAMEEN :" + NAMEEN);
				if (NAMEEN != null && !StandardUtils.isNameEN(NAMEEN))
					wrongInfo.append(";英文名称错误");

				// 发布日期
				String ISSUE_TIME = POIUtils.getColumValue(lineString, 3);
				log.info("ISSUE_TIME:" + ISSUE_TIME);
				if (ISSUE_TIME != null
						&& !StandardUtils.isDateFormat(ISSUE_TIME))
					wrongInfo.append(";发布日期格式错误");

				// 实施日期
				String ACT_TIME = POIUtils.getColumValue(lineString, 4);
				if (ACT_TIME != null && !StandardUtils.isDateFormat(ACT_TIME))
					wrongInfo.append(";实施日期格式错误");

				// 发布单位
				String ISSUE_DEPT = POIUtils.getColumValue(lineString, 5);
				log.info("ISSUE_DEPT:" + ISSUE_DEPT);

				// 提出单位
				String REQUEST_DEPT = POIUtils.getColumValue(lineString, 6);
				log.info("REQUEST_DEPT:" + REQUEST_DEPT);

				// 起草单位
				String DRAFT_DEPT = POIUtils.getColumValue(lineString, 7);
				log.info("DRAFT_DEPT:" + DRAFT_DEPT);

				// 起草人
				String DRAFTER = POIUtils.getColumValue(lineString, 8);
				log.info("DRAFTER:" + DRAFTER);

				// CCS
				String CCS_CODE = POIUtils.getColumValue(lineString, 9);
				log.info("CCS_CODE:" + CCS_CODE);
				if (CCS_CODE != null && !StandardUtils.isCCSCode(CCS_CODE))
					wrongInfo.append(";CCS 格式错误");

				// ICS
				String ICS_CODE = POIUtils.getColumValue(lineString, 10);
				log.info("ICS_CODE:" + ICS_CODE);
				if (ICS_CODE != null && !StandardUtils.isICSCode(ICS_CODE))
					wrongInfo.append(";ICS 格式错误");

				// 采标程度
				String ADOPT_GRADE = POIUtils.getColumValue(lineString, 11);
				log.info("ADOPT_GRADE:" + ADOPT_GRADE);

				// 采用标准号
				String ADOPT_STANDARD_CODE = POIUtils.getColumValue(lineString,
						12);
				log.info("CCS_CODE:" + CCS_CODE);

				// 采用标准名称
				String ADOPT_STANDARD_NAME = POIUtils.getColumValue(lineString,
						13);
				log.info("ADOPT_STANDARD_NAME:" + ADOPT_STANDARD_NAME);

				// 主题词
				String TOPIC = POIUtils.getColumValue(lineString, 14);
				log.info("TOPIC:" + TOPIC);

				// 范围
				String SCOPE = POIUtils.getColumValue(lineString, 15);
				log.info("SCOPE:" + SCOPE);

				// 引用文件
				String REFERENCE_FILE = POIUtils.getColumValue(lineString, 16);
				log.info("REFERENCE_FILE:" + REFERENCE_FILE);

				// 代替标准
				String REPLACE_STANDARD = POIUtils
						.getColumValue(lineString, 17);
				log.info("REPLACE_STANDARD:" + REPLACE_STANDARD);
				if (REPLACE_STANDARD != null
						&& !StandardUtils
								.isReplaceStandardCode(REPLACE_STANDARD))
					wrongInfo.append(";代替标准号格式错误");

				// 被代替标准
				String REPLACED_STANDARD = POIUtils.getColumValue(lineString,
						18);
				log.info("REPLACED_STANDARD:" + REPLACED_STANDARD);
				if (REPLACED_STANDARD != null
						&& !StandardUtils
								.isReplacedStandardCode(REPLACED_STANDARD))
					wrongInfo.append(";被代替标准号格式错误");

				// 标准状态
				String STATUS = POIUtils.getColumValue(lineString, 19);
				log.info("STATUS:" + STATUS);
				if (STATUS != null && !StandardUtils.isStatusCode(STATUS))
					wrongInfo.append(";标准状态错误");

				// 废止日期
				String CANCEL_TIME = POIUtils.getColumValue(lineString, 20);
				if (CANCEL_TIME != null && CANCEL_TIME != null
						&& !CANCEL_TIME.endsWith("")
						&& !StandardUtils.isDateFormat(CANCEL_TIME))
					wrongInfo.append(";废止日期格式错误");

				// 过渡期
				String INTERIM = POIUtils.getColumValue(lineString, 21);
				log.info("INTERIM:" + INTERIM);

				// 语种
				String LANGUAGE_CODE = POIUtils.getColumValue(lineString, 22);
				log.info("LANGUAGE_CODE:" + LANGUAGE_CODE);
				if (LANGUAGE_CODE != null
						&& !StandardUtils.isLanguageCode(LANGUAGE_CODE))
					wrongInfo.append(";语种拼写错误");

				// 页数. POI 工具类转换数字之后，默认的是 Double 类型，现转换为整数。
				String PAGE_NUMBER = POIUtils.getColumValue(lineString, 23);
				PAGE_NUMBER = StringUtils.substringBefore(PAGE_NUMBER, ".");
				log.info("PAGE_NUMBER:" + PAGE_NUMBER);
				if (PAGE_NUMBER != null
						&& !StandardUtils.isPageNumber(PAGE_NUMBER))
					wrongInfo.append(";页数错误");

				// 版本
				String EDITION = POIUtils.getColumValue(lineString, 24);
				log.info("EDITION:" + EDITION);

				// 主管部门
				String ATTACH_DEPT = POIUtils.getColumValue(lineString, 25);
				log.info("ATTACH_DEPT:" + ATTACH_DEPT);

				// 摘要
				String SUMMARY = POIUtils.getColumValue(lineString, 26);
				log.info("SUMMARY:" + SUMMARY);

				// 一级分类
				String CLASS_ONE_CODE = POIUtils.getColumValue(lineString, 27);
				log.info("CLASS_ONE_CODE:" + CLASS_ONE_CODE);
				if (CLASS_ONE_CODE != null
						&& !StandardUtils.isClassOneCode(CLASS_ONE_CODE))
					wrongInfo.append(";一级标准分类代码错误");

				// 二级分类
				String CLASS_TWO_CODE = POIUtils.getColumValue(lineString, 28);
				log.info("CLASS_TWO_CODE:" + CLASS_TWO_CODE);
				if (CLASS_TWO_CODE != null
						&& !StandardUtils.isClassTwoCode(CLASS_TWO_CODE))
					wrongInfo.append(";二级标准分类代码错误");

				// 三级分类
				String CLASS_THREE_CODE = POIUtils
						.getColumValue(lineString, 29);
				log.info("CLASS_THREE_CODE:" + CLASS_THREE_CODE);
				if (CLASS_THREE_CODE != null
						&& !StandardUtils.isClassThreeCode(STANDARD_CODE,
								CLASS_THREE_CODE))
					wrongInfo.append(";三级标准分类代码错误");

				// 四级分类
				String CLASS_FOUR_CODE = POIUtils.getColumValue(lineString, 30);
				log.info("CLASS_FOUR_CODE:" + CLASS_FOUR_CODE);
				log.info("STANDARD_CODE : " + STANDARD_CODE);
				log.info("isClassFourCode : "
						+ StandardUtils.isClassFourCode(STANDARD_CODE,
								CLASS_FOUR_CODE));
				if (CLASS_FOUR_CODE != null
						&& !StandardUtils.isClassFourCode(STANDARD_CODE,
								CLASS_FOUR_CODE))
					wrongInfo.append(";四级标准分类代码错误");

				// 备注
				String REMARK = POIUtils.getColumValue(lineString, 31);
				log.info("REMARK:" + REMARK);

				// 检验通过，写入 验证正确的 excel
				if (wrongInfo.length() == 0) {
					log.info(i + " line pass.");

					// 一行结束，准备录入条件
					row = sheetright.createRow(rownumright);

					row.createCell(0).setCellValue(STANDARD_CODE);
					row.createCell(1).setCellValue(NAMECN);
					row.createCell(2).setCellValue(NAMEEN);
					row.createCell(3).setCellValue(ISSUE_TIME);
					row.createCell(4).setCellValue(ACT_TIME);
					row.createCell(5).setCellValue(ISSUE_DEPT);
					row.createCell(6).setCellValue(REQUEST_DEPT);
					row.createCell(7).setCellValue(DRAFT_DEPT);
					row.createCell(8).setCellValue(DRAFTER);
					row.createCell(9).setCellValue(CCS_CODE);
					row.createCell(10).setCellValue(ICS_CODE);
					row.createCell(11).setCellValue(ADOPT_GRADE);
					row.createCell(12).setCellValue(ADOPT_STANDARD_CODE);
					row.createCell(13).setCellValue(ADOPT_STANDARD_NAME);
					row.createCell(14).setCellValue(TOPIC);
					row.createCell(15).setCellValue(SCOPE);
					row.createCell(16).setCellValue(REFERENCE_FILE);
					row.createCell(17).setCellValue(REPLACE_STANDARD);
					row.createCell(18).setCellValue(REPLACED_STANDARD);
					row.createCell(19).setCellValue(STATUS);
					row.createCell(20).setCellValue(CANCEL_TIME);
					row.createCell(21).setCellValue(INTERIM);
					row.createCell(22).setCellValue(LANGUAGE_CODE);
					row.createCell(23).setCellValue(PAGE_NUMBER);
					row.createCell(24).setCellValue(EDITION);
					row.createCell(25).setCellValue(ATTACH_DEPT);
					row.createCell(26).setCellValue(SUMMARY);
					row.createCell(27).setCellValue(CLASS_ONE_CODE);
					row.createCell(28).setCellValue(CLASS_TWO_CODE);
					row.createCell(29).setCellValue(CLASS_THREE_CODE);
					row.createCell(30).setCellValue(CLASS_FOUR_CODE);
					row.createCell(31).setCellValue(REMARK);

					// 准备写入 excel 的行数
					rownumright++;

					rightallnum++;

					// 返回提示信息
					message = "验证通过 ： " + STANDARD_CODE + "   " + NAMECN;

				} else {
					log.info(i + " line dose not pass.");
					row = sheetwrong.createRow(rownumwrong);
					row.createCell(0).setCellValue(
							POIUtils.getColumValue(lineString, 0));
					row.createCell(1).setCellValue(
							POIUtils.getColumValue(lineString, 1));
					row.createCell(2).setCellValue(
							POIUtils.getColumValue(lineString, 2));
					row.createCell(3).setCellValue(
							POIUtils.getColumValue(lineString, 3));
					row.createCell(4).setCellValue(
							POIUtils.getColumValue(lineString, 4));
					row.createCell(5).setCellValue(
							POIUtils.getColumValue(lineString, 5));
					row.createCell(6).setCellValue(
							POIUtils.getColumValue(lineString, 6));
					row.createCell(7).setCellValue(
							POIUtils.getColumValue(lineString, 7));
					row.createCell(8).setCellValue(
							POIUtils.getColumValue(lineString, 8));
					row.createCell(9).setCellValue(
							POIUtils.getColumValue(lineString, 9));
					row.createCell(10).setCellValue(
							POIUtils.getColumValue(lineString, 10));
					row.createCell(11).setCellValue(
							POIUtils.getColumValue(lineString, 11));
					row.createCell(12).setCellValue(
							POIUtils.getColumValue(lineString, 12));
					row.createCell(13).setCellValue(
							POIUtils.getColumValue(lineString, 13));
					row.createCell(14).setCellValue(
							POIUtils.getColumValue(lineString, 14));
					row.createCell(15).setCellValue(
							POIUtils.getColumValue(lineString, 15));
					row.createCell(16).setCellValue(
							POIUtils.getColumValue(lineString, 16));
					row.createCell(17).setCellValue(
							POIUtils.getColumValue(lineString, 17));
					row.createCell(18).setCellValue(
							POIUtils.getColumValue(lineString, 18));
					row.createCell(19).setCellValue(
							POIUtils.getColumValue(lineString, 19));
					row.createCell(20).setCellValue(
							POIUtils.getColumValue(lineString, 20));
					row.createCell(21).setCellValue(
							POIUtils.getColumValue(lineString, 21));
					row.createCell(22).setCellValue(
							POIUtils.getColumValue(lineString, 22));
					row.createCell(23).setCellValue(
							POIUtils.getColumValue(lineString, 23));
					row.createCell(24).setCellValue(
							POIUtils.getColumValue(lineString, 24));
					row.createCell(25).setCellValue(
							POIUtils.getColumValue(lineString, 25));
					row.createCell(26).setCellValue(
							POIUtils.getColumValue(lineString, 26));
					row.createCell(27).setCellValue(
							POIUtils.getColumValue(lineString, 27));
					row.createCell(28).setCellValue(
							POIUtils.getColumValue(lineString, 28));
					row.createCell(29).setCellValue(
							POIUtils.getColumValue(lineString, 29));
					row.createCell(30).setCellValue(
							POIUtils.getColumValue(lineString, 30));
					row.createCell(31).setCellValue(
							POIUtils.getColumValue(lineString, 31));

					String info = StringUtils.removeStart(wrongInfo.toString(),
							";");

					rownumwrong++;
					// 提示错误信息，在记录错误题录信息的文件中，行数
					wrongList.add("第 " + (wrongallno) + " 行错误 ：" + info);
					wrongallno++;

					message = "验证未通过 ： " + STANDARD_CODE + "   " + NAMECN;

				}

				/**
				 * 
				 * 仅在这上面处理任务即可
				 * 
				 **/

				/**
				 * 下面这段代码不要改动，仅是为了更新 progrss 用
				 * 
				 * */

				// 根据 i 的变化，分不同的情况，更新 progress ，和具体的业务没有关系
				// 为了进度条显示的更加合理，把任务数量分成了几个区间。
				// 否则:
				// 当任务很少的时候，进度条没有到 100%，任务已经完成了。
				// 当任务很多的时候，进度条已经进行到 到 100%，但任务还没有完成。
				if (count <= 100) {
					// 总数小于 100 ，progress 增长设计
					int divisor = 100 / count;

					if (i * divisor <= 100 && i <= count) {
						progress = i * divisor;

						if (i == count) {
							progress = 100;
							out.println(" **************** update progress = "
									+ progress);
						}

						// 更新参数
						setProgress(progress);
					}

				} else if (100 < count) {
					// 总数大于 100 ，progress 增长设计

					// 如果 progress 已经接近 100 ，但任务总数还没完成，则不更新 progress，继续处理任务。
					if (progress == 98 && i < count) {
						i++;
						continue;
					}

					if (i % step == 0) {// progress 增长 1
										// 的时机，经过四舍五入 Math.round
						progress++;
						out.println(" **************** update progress = "
								+ progress);
					}

					// 更新参数
					setProgress(progress);

				}

				i++;

				/**
				 * 上面这段代码不要改动，仅是为了更新 progrss 用
				 * 
				 * */

			}// end while

			return null;
		}

		/**
		 * 任务完成之后的动作。
		 */
		@Override
		public void done() {
			Toolkit.getDefaultToolkit().beep();

			log.info("task done.");

			// 最后结束的时候，结果写入文件
			try {

				wbright.write(outRightSteam);
				outRightSteam.close();

				// 写入错误信息
				log.info("wrongList :" + wrongList);
				if (wrongList.size() != 0) {
					wbwrong.write(outWrongSteam);
					outWrongSteam.close();
					FileUtils.writeLines(
							new File(wrong_standard_Info_filepath), wrongList);
				}
				// 验证完成，改名
				excelFile.renameTo(new File(excelFile_rename));

				// 删除模板文件
				// ftemp.delete();

			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				// 此处弹出对话框
				JOptionPane.showMessageDialog(JPanelSwingWorkerCheckTilu.this,
						"请关闭打开的 excel 文件2");
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block

				e.printStackTrace();
			}

			buttonStart.setEnabled(true);

		}

	}

	/**
	 * 跟踪 Task 类中 progress 变量变化，当 progress 变量 变化时，直接触发这个方法，更新组件信息。
	 * 
	 * progress 变化范围为[0,100]
	 * 
	 */
	public void propertyChange(PropertyChangeEvent evt) {
		if ("progress" == evt.getPropertyName()) {

			// 下面这个 progress ，数值取自 Task 类中的默认变量 progress
			int progress = (Integer) evt.getNewValue();

			// taskOutput.append(message);
			if (task.isCancelled()) {
				log.info("task isCancelled()");
				buttonStart.setEnabled(true);
			}

			// 返回提示信息
			if (progress == 100)
				message = "验证题录总数 " + (allnum - 2) + " ,通过验证 " + rightallnum
						+ " ,未通过验证 " + (wrongallno - 3);

			// lable 信息更新
			messageLabel.setText(this.message);
			// textField 信息更新
			// textField.setText(this.message);
			// progressBar 信息更新

			progressBar.setValue(progress);

		}

	}

}
